﻿/**
 * 格类的构造方法。
 */
function Grid() {
    this.mUsed = false  // 使用则为 true，否则为 false
}

/**
 * 带颜色的格类的构造方法。
 */
function ColorGrid() {
    Grid.call(this)
    this.mColor = "rgb(0, 0, 0)"    // 颜色
}

// 方块形状
const Shape = {
    ONE: 0,     // 形状1
    TWO: 1,     // 形状2
    THREE: 2,   // 形状3
    FOUR: 3     // 形状4
} 

/**
 * 方块类的构造方法。
 */
function Block() {
    this.mBlocks = new Array(Const.BLOCK_GRID_COUNT_V)              // 方块数据   
    const red = Math.floor(Math.random() * 1000) % 256
    const green = Math.floor(Math.random() * 1000) % 256
    const blue = Math.floor(Math.random() * 1000) % 256
    this.mColor = "rgb(" + red + "," + green + "," + blue + ")"     // 颜色
    this.mDrawer = null                                             // 绘图者
    this.mGameBoard = null                                          // 游戏区域
    this.mLine = 3                                                  // 当前所在列(左)
    this.mRow = -1                                                  // 当前所在行(上)
    this.mShape = Shape.ONE                                         // 形状
    for (var i = 0; i < Const.BLOCK_GRID_COUNT_V; i++) {
        this.mBlocks[i] = new Array(Const.BLOCK_GRID_COUNT_H)
        for (var j = 0; j < Const.BLOCK_GRID_COUNT_H; j++) {
            this.mBlocks[i][j] = new Grid()
        }
    }

    /**
     * 绘制自身。
     * @param block 方块
     */
    this.draw = function(block) {
        for (var i = 0; i < Const.BLOCK_GRID_COUNT_H; i++) {
            for (var j = 0; j < Const.BLOCK_GRID_COUNT_V; j++) {
                if (!block.mBlocks[i][j].mUsed) {
                    continue
                }
    
                const left = Const.GRID_SIZE * (block.mLine + j)
                const top = Const.GRID_SIZE * (block.mRow + i)
                block.mDrawer.fillStyle = block.mColor
                block.mDrawer.fillRect(left, top, Const.GRID_SIZE, Const.GRID_SIZE)
                Block.drawEdge(block.mDrawer, left, top)
            }
        }
    
        block.mGameBoard.repaint()
    }

    this.enterGameBoard = Block_EnterGameboard
    this.enterPreview = Block_EnterPreview
    this.eraseRect = Block_EraseRect
}

/*
 * 画矩形的边框，使矩形具有立体效果。
 * @param drawer    绘图者
 * @param left, top 矩形的左上角坐标
 */
Block.drawEdge = function(drawer, left, top) {
    const right = left + Const.GRID_SIZE - 1
    const bottom = top + Const.GRID_SIZE - 1

    drawer.fillStyle = "rgb(214, 211, 206)"
    drawer.fillRect(left, top, Const.GRID_SIZE - 1, 1)
    drawer.fillRect(left, top, 1, Const.GRID_SIZE - 1)

    drawer.fillStyle = "rgb(255, 255, 255)"
    drawer.fillRect(left + 1, top + 1, Const.GRID_SIZE - 3, 1)
    drawer.fillRect(left + 1, top + 1, 1, Const.GRID_SIZE - 3)

    drawer.fillStyle = "rgb(66, 65, 66)"
    drawer.fillRect(right, top, 1, Const.GRID_SIZE)
    drawer.fillRect(left, bottom, Const.GRID_SIZE - 1, 1)

    drawer.fillStyle = "rgb(132, 130, 132)"
    drawer.fillRect(right - 1, top + 1, 1, Const.GRID_SIZE - 2)
    drawer.fillRect(left + 1, bottom - 1, Const.GRID_SIZE - 3, 1)
}

/**
 * 进入游戏区域。
 * @param block     方块
 * @param gameBoard 游戏区域
 * @param drawer    绘图者
 */
function Block_EnterGameboard(block, gameBoard, drawer) {
    block.mGameBoard = gameBoard
    block.mDrawer = drawer
    block.draw(block)
}

/**
 * 进入预览区域。
 * @param block     方块
 * @param drawer    绘图者
 */
function Block_EnterPreview(block, drawer) {
    const x = (Const.PREVIEW_WIDTH - Const.GRID_SIZE * 3) / 2
    const y = Const.PREVIEW_HEIGHT / 2 - Const.GRID_SIZE * 2

    // 遍历所有格，跳过无效的，画有效的
    for (var i = 0; i < Const.BLOCK_GRID_COUNT_H; i++) {
        for (var j = 0; j < Const.BLOCK_GRID_COUNT_V; j++) {
            if (!block.mBlocks[i][j].mUsed) {
                continue
            }
            drawer.fillStyle = block.mColor
            drawer.fillRect(x + Const.GRID_SIZE * j, y + Const.GRID_SIZE * i, Const.GRID_SIZE, Const.GRID_SIZE)
            Block.drawEdge(drawer, x + Const.GRID_SIZE * j, y + Const.GRID_SIZE * i)
        }
    }
}

/**
 * 擦除矩形。
 * @param block     方块
 * @param x, y      矩形左上角坐标
 * @param width     矩形宽度
 * @param height    矩形高度
 */
function Block_EraseRect(block, x, y, width, height) {
    block.mDrawer.fillStyle = Const.GAME_BOARD_COLOR
    block.mDrawer.fillRect(x, y, width, height)
}

/**
 * 下落。
 * @param block 方块
 * @return 总是 true
 */
function Block_MoveDown(block) {
    block.erase(block)
    block.mRow++
    block.draw(block)

    return true
}

/**
 * 左移。
 * @param block 方块
 */
function Block_MoveLeft(block) {
    block.erase(block)
    block.mLine--
    block.draw(block)
}

/**
 * 右移。
 * @param block 方块
 */
function Block_MoveRight(block) {
    block.erase(block)
    block.mLine++
    block.draw(block)
}
